using System;
using System.Collections;
using System.Collections.Generic;
using Main.Details;
using Main.Event;
using Main.Inventory;
using Main.Save;
using Main.Transition;
using Unity.Mathematics;
using UnityEngine;
using ZSW.Framework;

namespace Main.Item
{
    public class ItemManager : ZSWF_Singleton<ItemManager>, ISaveable
    {
        public ItemDataList_SO itemData;

        public Transform itemParent;
        public BaseItem basePrefab;
        public BaseItem bouncePrefab;

        /// <summary>
        /// 记录场景中的物品
        /// </summary>
        /// <returns></returns>
        private Dictionary<string, List<SceneItem>> sceneItemDic = new Dictionary<string, List<SceneItem>>();
        private Dictionary<string, List<SceneFurniture>> sceneFurnitureDic = new Dictionary<string, List<SceneFurniture>>();

        public string GUID => GetComponent<DataGUID>().guid;

        public override void Init()
        {
            base.Init();
            sceneItemDic = new Dictionary<string, List<SceneItem>>();
            sceneFurnitureDic = new Dictionary<string, List<SceneFurniture>>();
            MainEventSystem.BeforeLoadSceneEvent += OnBeforeLoadScene;
            MainEventSystem.AfterLoadSceneEvent += OnAfterLoadScene;
            MainEventSystem.InstantiateItemEvent += OnCreateItem;
            MainEventSystem.DropItemEvent += OnDropItem;
            // 建造设备时
            MainEventSystem.BuildFurnitureEvent += OnBuildFurniture;
            MainEventSystem.StartNewGameEvent += OnStartNewGame;

            ISaveable saveable = this;
            saveable.RegisterSaveable();
        }

        private void OnStartNewGame(int obj)
        {
            sceneItemDic.Clear();
            sceneFurnitureDic.Clear();
        }

        private void OnBuildFurniture(Vector3 mouseWorldPosition, int itemId)
        {
            if (ZSWF_IOCContainer.Get<BluePrintDataList_SO>().TryGetBluePrintDetails(itemId, out var bluePrintDetails))
            {
                var buildItem = Instantiate(bluePrintDetails.buildPrefab, mouseWorldPosition, quaternion.identity, itemParent);
                if (buildItem.GetComponent<Box>())
                {
                    buildItem.GetComponent<Box>().index = ZSWF_IOCContainer.Get<InventoryManager>().boxDataDic.Count;
                    buildItem.GetComponent<Box>().InitBox(buildItem.GetComponent<Box>().index);
                }
            }
        }

        public bool TryGetItemDetails(int id, out ItemDetails itemDetails)
        {
            itemDetails = null;
            foreach (var item in itemData.ItemDetailsList)
            {
                if (item.ItemID == id)
                {
                    itemDetails = item;
                    return true;
                }
            }
            return false;
        }

        private void OnAfterLoadScene()
        {
            itemParent = GameObject.FindWithTag(Settings.ItemParent).transform;
            RecreateAllItems();
            RebuildFurniture();
        }

        private void OnBeforeLoadScene()
        {
            GetAllSceneItems();
            GetAllSceneFurniture();
        }

        public void OnCreateItem(int itemID, Vector3 Position)
        {
            var item = Instantiate(bouncePrefab, Position, Quaternion.identity, itemParent);
            item.ItemID = itemID;
            item.Init();

            item.GetComponent<ItemBounce>().SetTarget(Position, Vector3.up);
        }

        public void OnDropItem(int itemID, Vector3 mousePos, ItemType itemType)
        {
            //TODO: 物品掉落效果
            if (itemType != ItemType.Seed)
            {
                Vector3 playerPos = Player.Transform.position;
                var item = Instantiate(bouncePrefab, playerPos, Quaternion.identity, itemParent);
                item.ItemID = itemID;
                var direction = (mousePos - playerPos).normalized;
                item.Init();
                item.GetComponent<ItemBounce>().SetTarget(mousePos, direction);
            }
        }

        private void GetAllSceneItems()
        {
            List<SceneItem> currentSceneItems = new List<SceneItem>();

            foreach (var item in FindObjectsOfType<BaseItem>())
            {
                SceneItem sceneItem = new SceneItem
                {
                    itemID = item.ItemID,
                    position = new SerializableVector3(item.transform.position)
                };
                currentSceneItems.Add(sceneItem);
            }

            // 记录当前场景中的物品
            if (!sceneItemDic.ContainsKey(SceneTransitionManager.CurrentScene))
            {
                sceneItemDic.Add(SceneTransitionManager.CurrentScene, currentSceneItems);
            }
            else
            {
                sceneItemDic[SceneTransitionManager.CurrentScene] = currentSceneItems;
            }
        }

        /// <summary>
        /// 获取当前场景中的家具
        /// </summary>
        private void GetAllSceneFurniture()
        {
            List<SceneFurniture> currentSceneFurniture = new List<SceneFurniture>();

            foreach (var item in FindObjectsOfType<Furniture>())
            {
                SceneFurniture sceneFurniture = new SceneFurniture
                {
                    itemID = item.ItemID,
                    position = new SerializableVector3(item.transform.position)
                };
                if (item.GetComponent<Box>())
                {
                    sceneFurniture.boxIndex = item.GetComponent<Box>().index;
                }
                currentSceneFurniture.Add(sceneFurniture);
            }

            // 记录当前场景中的物品
            if (!sceneFurnitureDic.ContainsKey(SceneTransitionManager.CurrentScene))
            {
                sceneFurnitureDic.Add(SceneTransitionManager.CurrentScene, currentSceneFurniture);
            }
            else
            {
                sceneFurnitureDic[SceneTransitionManager.CurrentScene] = currentSceneFurniture;
            }
        }

        private void RecreateAllItems()
        {
            if (sceneItemDic.TryGetValue(SceneTransitionManager.CurrentScene, out var sceneItems))
            {
                foreach (var old in FindObjectsOfType<BaseItem>())
                {
                    Destroy(old.gameObject);
                }

                foreach (var item in sceneItems)
                {
                    OnCreateItem(item.itemID, item.position.ToVector3());
                }
            }
        }

        private void RebuildFurniture()
        {
            List<SceneFurniture> sceneFurniture = new List<SceneFurniture>();

            if (sceneFurnitureDic.TryGetValue(SceneTransitionManager.CurrentScene, out sceneFurniture))
            {
                if (sceneFurniture != null)
                {
                    foreach (var furniture in sceneFurniture)
                    {
                        if (ZSWF_IOCContainer.Get<BluePrintDataList_SO>().TryGetBluePrintDetails(furniture.itemID, out var bluePrintDetails))
                        {
                            var buildItem = Instantiate(bluePrintDetails.buildPrefab, furniture.position.ToVector3(), quaternion.identity, itemParent);
                            if (buildItem.GetComponent<Box>())
                            {
                                buildItem.GetComponent<Box>().InitBox(furniture.boxIndex);
                            }
                        }
                    }
                }
            }
        }

        public GameSaveData GenerateSaveData()
        {
            GetAllSceneItems();
            GetAllSceneFurniture();

            var data = new GameSaveData();
            data.sceneItemDict = sceneItemDic;
            data.sceneFurnitureDict = sceneFurnitureDic;

            return data;
        }

        public void RestoreData(GameSaveData data)
        {
            sceneItemDic = data.sceneItemDict;
            sceneFurnitureDic = data.sceneFurnitureDict;

            RecreateAllItems();
            RebuildFurniture();
        }
    }
}

